package com.k2data.k2app.controller;

import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.k2data.k2app.common.MyConstant;
import com.k2data.k2app.common.OrikaMapperFactory;
import com.k2data.k2app.constant.Constant;
import com.k2data.k2app.constant.ResponseCode;
import com.k2data.k2app.domain.EventCond;
import com.k2data.k2app.domain.EventDTO;
import com.k2data.k2app.domain.EventDeviceDTO;
import com.k2data.k2app.domain.po.EventCustomer;
import com.k2data.k2app.domain.po.EventDevice;
import com.k2data.k2app.domain.po.EventFault;
import com.k2data.k2app.domain.po.EventMaintenance;
import com.k2data.k2app.exception.K2ResponseException;
import com.k2data.k2app.mapper.EventCustomerMapper;
import com.k2data.k2app.mapper.EventDeviceMapper;
import com.k2data.k2app.mapper.EventFaultMapper;
import com.k2data.k2app.mapper.EventMaintenanceMapper;
import com.k2data.k2app.response.CommonResultResponse;
import com.k2data.k2app.response.PageInfo;
import com.k2data.k2app.response.ResponseHelper;
import com.k2data.k2app.rest.SysClient;
import com.k2data.k2app.rest.domain.DictRest;
import com.k2data.k2app.service.EventService;
import com.k2data.k2app.service.KmxService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @author lidong9144@163.com 17-3-17.
 */
@RestController
@RequestMapping("/events")
public class EventController {

    private final SysClient sysClient;

    private final EventService eventService;
    private final EventFaultMapper eventFaultMapper;
    private final EventMaintenanceMapper eventMaintenanceMapper;
    private final KmxService kmxService;
    private final EventDeviceMapper eventDeviceMapper;
    private final EventCustomerMapper eventCustomerMapper;

    @Autowired
    public EventController(EventService eventService, EventFaultMapper eventFaultMapper,
                           EventMaintenanceMapper eventMaintenanceMapper,
                           KmxService kmxService, SysClient sysClient,
                           EventDeviceMapper eventDeviceMapper, EventCustomerMapper eventCustomerMapper) {
        this.eventService = eventService;
        this.eventFaultMapper = eventFaultMapper;
        this.eventMaintenanceMapper = eventMaintenanceMapper;
        this.kmxService = kmxService;
        this.sysClient = sysClient;
        this.eventDeviceMapper = eventDeviceMapper;
        this.eventCustomerMapper = eventCustomerMapper;
    }

    @ApiOperation(value = "添加事件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "event", value = "event", required = true, dataType = "EventDevice", paramType = "body")
    })
    @PostMapping(value = "", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<CommonResultResponse> postEvent(@RequestBody EventDevice event) throws Exception {
        return ResponseHelper.success(eventService.insertEvent(event));
    }

    @ApiOperation(value = "更新事件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "eventId", required = true, dataType = "Long", paramType = "path"),
            @ApiImplicitParam(name = "event", value = "event", required = true, dataType = "EventDevice", paramType = "body")
    })
    @PutMapping(value = "/{id}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<CommonResultResponse> putEvent(@PathVariable("id") Long id,
                                                         @RequestBody EventDevice event) throws Exception {
        event.setId(id);

        return ResponseHelper.success(eventService.updateEvent(event));
    }

    @ApiOperation(value = "删除事件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "id", required = true, dataType = "Long", paramType = "path")
    })
    @DeleteMapping(value = "/{id}")
    public ResponseEntity<CommonResultResponse> deleteEvent(@PathVariable("id") Long id) throws Exception {
        return ResponseHelper.success(eventDeviceMapper.deleteByPrimaryKey(id));
    }

    @ApiOperation(value = "添加客户事件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "event", value = "event", required = true, dataType = "EventCustomer", paramType = "body")
    })
    @PostMapping(value = "/customers", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<CommonResultResponse> postEventCustomer(@RequestBody EventCustomer event) throws Exception {
        return ResponseHelper.success(eventService.insertEventCustomer(event));
    }

    @ApiOperation(value = "更新客户事件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "eventId", required = true, dataType = "Long", paramType = "path"),
            @ApiImplicitParam(name = "event", value = "event", required = true, dataType = "EventCustomer", paramType = "body")
    })
    @PutMapping(value = "/customers/{id}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<CommonResultResponse> putEventCustomer(@PathVariable("id") Long id,
                                                                 @RequestBody EventCustomer event) throws Exception {
        event.setId(id);

        return ResponseHelper.success(eventService.updateEventCustomer(event));
    }

    @ApiOperation(value = "删除客户事件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "eventId", required = true, dataType = "Long", paramType = "path")
    })
    @DeleteMapping(value = "/customers/{id}")
    public ResponseEntity<CommonResultResponse> deleteEventCustomer(@PathVariable("id") Long id) throws Exception {
        return ResponseHelper.success(eventCustomerMapper.deleteByPrimaryKey(id));
    }

    @ApiOperation(value = "添加故障事件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "event", value = "event", required = true, dataType = "EventFault", paramType = "body")
    })
    @PostMapping(value = "/faults", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<CommonResultResponse> postEventFault(@RequestBody EventFault event) throws Exception {
        return ResponseHelper.success(eventService.insertEventFault(event));
    }

    @ApiOperation(value = "更新故障事件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "eventId", required = true, dataType = "Long", paramType = "path"),
            @ApiImplicitParam(name = "event", value = "event", required = true, dataType = "EventFault", paramType = "body")
    })
    @PutMapping(value = "/faults/{id}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<CommonResultResponse> putEventFault(@PathVariable("id") Long id,
                                                                 @RequestBody EventFault event) throws Exception {
        event.setId(id);

        return ResponseHelper.success(eventService.updateEventFault(event));
    }

    @ApiOperation(value = "删除故障事件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "eventId", required = true, dataType = "Long", paramType = "path")
    })
    @DeleteMapping(value = "/faults/{id}")
    public ResponseEntity<CommonResultResponse> deleteEventFault(@PathVariable("id") Long id) throws Exception {
        return ResponseHelper.success(eventFaultMapper.deleteByPrimaryKey(id));
    }

    @ApiOperation(value = "添加维修事件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "event", value = "event", required = true, dataType = "EventMaintenance", paramType = "body")
    })
    @PostMapping(value = "/maintenances", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<CommonResultResponse> postEventMaintenance(@RequestBody EventMaintenance event) throws Exception {
        return ResponseHelper.success(eventService.insertEventMaintenance(event));
    }

    @ApiOperation(value = "更新维修事件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "eventId", required = true, dataType = "Long", paramType = "path"),
            @ApiImplicitParam(name = "event", value = "event", required = true, dataType = "EventMaintenance", paramType = "body")
    })
    @PutMapping(value = "/maintenances/{id}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<CommonResultResponse> putEventMaintenance(@PathVariable("id") Long id,
                                                              @RequestBody EventMaintenance event) throws Exception {
        event.setId(id);

        return ResponseHelper.success(eventService.updateEventMaintenance(event));
    }

    @ApiOperation(value = "删除维修事件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "eventId", required = true, dataType = "Long", paramType = "path")
    })
    @DeleteMapping(value = "/maintenances/{id}")
    public ResponseEntity<CommonResultResponse> deleteEventMaintenance(@PathVariable("id") Long id) throws Exception {
        return ResponseHelper.success(eventMaintenanceMapper.deleteByPrimaryKey(id));
    }

    @ApiOperation(value = "异常事件")
    @GetMapping(value = "")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "types", value = "事件类型, 默认查全部(event, fault, maintenance)", allowMultiple = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "startDate", value = "开始时间", dataType = "date", paramType = "query"),
            @ApiImplicitParam(name = "endDate", value = "结束时间", dataType = "date", paramType = "query"),
            @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "每页大小(默认 30)", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "orderBy", value = "排序(start_time desc , start_time asc, update_time desc, update_time asc)", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "eventName", value = "事件名称", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "deviceName", value = "设备名称", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "owner", value = "负责人", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "eventType", value = "事件类型", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "status", value = "状态", dataType = "string", paramType = "query")
    })
    public ResponseEntity<CommonResultResponse> getEvents(
            @RequestParam(value = "startDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startDate,
            @RequestParam(value = "endDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endDate,
            @RequestParam(value = "pageNum", required = false) Integer pageNum,
            @RequestParam(value = "pageSize", required = false) Integer pageSize,
            @RequestParam(value = "orderBy", required = false) String orderBy,
            @RequestParam(value = "types", required = false) List<String> types,
            @RequestParam(value = "eventName", required = false) String eventName,
            @RequestParam(value = "deviceName", required = false) String deviceName,
            @RequestParam(value = "owner", required = false) String owner,
            @RequestParam(value = "eventType", required = false) String eventType,
            @RequestParam(value = "status", required = false) String status
    ) throws Exception {
        EventCond cond = new EventCond();
        cond.setStartTimeGreater(startDate);
        cond.setStartTimeLess(endDate);
        cond.setEventType(eventType);
        cond.setDeviceNameLike(deviceName);
        cond.setEventNameLike(eventName);
        cond.setOwner(owner);
        cond.setStatus(status);
        if (types == null) {
            cond.setContainEvent(true);
            cond.setContainFault(true);
            cond.setContainMaintenance(true);
        } else {
            if (types.contains(MyConstant.EVENT_TYPE)) {
                cond.setContainEvent(true);
            }
            if (types.contains(MyConstant.FAULT_TYPE)) {
                cond.setContainFault(true);
            }
            if (types.contains(MyConstant.MAINTENANCE_TYPE)) {
                cond.setContainMaintenance(true);
            }
        }
        if (orderBy != null
                && !("start_time desc".equals(orderBy)
                || "start_time asc".equals(orderBy)
                || "update_time desc".equals(orderBy)
                || "update_time asc".equals(orderBy))) {
            throw new K2ResponseException(ResponseCode.GENERAL_CLIENT_ERROR, "Request param error, 'orderBy' must be one of (start_time desc , start_time asc, update_time desc, update_time asc).");
        }
        cond.setOrderBy(orderBy);

        int pageNumReal = pageNum == null ? 1 : pageNum;
        int pageSizeReal = pageSize == null ? Constant.DEFAULT_PAGE_SIZE : pageSize;

        int total = eventDeviceMapper.selectAllEvent(cond).size();

        PageHelper.startPage(pageNumReal, pageSizeReal);
        EventDTO eventDTO = eventService.getAllEventList(cond);
        List<EventDTO> list = eventDTO.getEventList();

        PageInfo pageInfo = new PageInfo(pageNumReal, pageSizeReal, total);

        return ResponseHelper.success(list, pageInfo);
    }

    @ApiOperation(value = "故障数量统计")
    @GetMapping(value = "/faults/count")
    public ResponseEntity<CommonResultResponse> getCount() throws Exception {
        EventDTO dto = new EventDTO();
        dto.setCount(eventFaultMapper.selectCount(null));

        DictRest rest = sysClient.get(MyConstant.DICT_FAULT_TYPE);

        dto.setTypeCount(rest.getResult().size());
        dto.setStartTime(kmxService.getKmxStartTime());
        dto.setEndTime(LocalDateTime.now());

        return ResponseHelper.success(dto);
    }

    @ApiOperation(value = "故障类型")
    @GetMapping(value = "/faults/types")
    public ResponseEntity<CommonResultResponse> getFaultType() throws Exception {
        return ResponseHelper.success(eventFaultMapper.selectTypes());
    }

    @ApiOperation(value = "故障列表")
    @GetMapping(value = "/faults")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startDate", value = "开始时间", dataType = "date", paramType = "query"),
            @ApiImplicitParam(name = "endDate", value = "结束时间", dataType = "date", paramType = "query"),
            @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "每页大小(默认 30)", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "order", value = "(desc, asc)", dataType = "string", paramType = "query")
    })
    public ResponseEntity<CommonResultResponse> getFaultList(
            @RequestParam(value = "startDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam(value = "endDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate,
            @RequestParam(value = "pageNum", required = false) Integer pageNum,
            @RequestParam(value = "pageSize", required = false) Integer pageSize,
            @RequestParam(value = "order", required = false) String order) throws Exception {
        EventFault cond = new EventFault();
        cond.setStartTimeGreater(startDate);
        cond.setStartTimeLess(endDate);
        if ("desc".equals(order)) {
            cond.setOrderBy("start_time DESC");
        }

        int pageNumReal = pageNum == null ? 1 : pageNum;
        int pageSizeReal = pageSize == null ? Constant.DEFAULT_PAGE_SIZE : pageSize;
        int count = eventFaultMapper.selectCount(cond);

        PageHelper.startPage(pageNumReal, pageSizeReal);
        PageInfo pageInfo = new PageInfo(pageNumReal, pageSizeReal, count);

        List<EventDeviceDTO> list = Lists.newArrayList();

        List<EventDevice> source = eventFaultMapper.selectList(cond);
        for (EventDevice eventDevice : source) {
            EventDeviceDTO dto = OrikaMapperFactory.getMapper().map(eventDevice, EventDeviceDTO.class);
            list.add(dto);
        }

        return ResponseHelper.success(list, pageInfo);
    }

    @ApiOperation(value = "维修列表")
    @GetMapping(value = "/maintenances")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startDate", value = "开始时间", dataType = "date", paramType = "query"),
            @ApiImplicitParam(name = "endDate", value = "结束时间", dataType = "date", paramType = "query"),
            @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "每页大小(默认 30)", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "order", value = "(desc, asc)", dataType = "string", paramType = "query")
    })
    public ResponseEntity<CommonResultResponse> getMaintenanceList(
            @RequestParam(value = "startDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam(value = "endDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate,
            @RequestParam(value = "pageNum", required = false) Integer pageNum,
            @RequestParam(value = "pageSize", required = false) Integer pageSize,
            @RequestParam(value = "order", required = false) String order) throws Exception {
        EventMaintenance cond = new EventMaintenance();
        cond.setStartTimeGreater(startDate);
        cond.setStartTimeLess(endDate);
        if ("desc".equals(order)) {
            cond.setOrderBy("start_time DESC");
        }

        int pageNumReal = pageNum == null ? 1 : pageNum;
        int pageSizeReal = pageSize == null ? Constant.DEFAULT_PAGE_SIZE : pageSize;
        int count = eventMaintenanceMapper.selectCount(cond);

        PageHelper.startPage(pageNumReal, pageSizeReal);
        PageInfo pageInfo = new PageInfo(pageNumReal, pageSizeReal, count);

        List<EventDeviceDTO> list = Lists.newArrayList();

        List<EventDevice> source = eventMaintenanceMapper.selectList(cond);
        for (EventDevice eventDevice : source) {
            EventDeviceDTO dto = OrikaMapperFactory.getMapper().map(eventDevice, EventDeviceDTO.class);
            list.add(dto);
        }

        return ResponseHelper.success(list, pageInfo);
    }

    @ApiOperation(value = "故障事件类型数量")
    @GetMapping(value = "/faults/types/count")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "deviceId", value = "deviceId", dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "customer_id", value = "客户id", dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "startDate", value = "开始时间", dataType = "date", paramType = "query"),
            @ApiImplicitParam(name = "endDate", value = "结束时间", dataType = "date", paramType = "query")
    })
    public ResponseEntity<CommonResultResponse> getFaultBarChart(
            @RequestParam(value = "deviceId", required = false) Long deviceId,
            @RequestParam(value = "customer_id", required = false) Long customerId,
            @RequestParam(value = "startDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startDate,
            @RequestParam(value = "endDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endDate
    ) throws Exception {
        EventCond cond = new EventCond();
        cond.setDeviceId(deviceId);
        cond.setCustomerId(customerId);
        cond.setStartTimeGreater(startDate);
        cond.setStartTimeLess(endDate);

        return ResponseHelper.success(eventService.faultBarChart(cond));
    }

    @ApiOperation(value = "维修事件类型数量")
    @GetMapping(value = "/maintenances/types/count")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "deviceId", value = "deviceId", dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "startDate", value = "开始时间", dataType = "date", paramType = "query"),
            @ApiImplicitParam(name = "endDate", value = "结束时间", dataType = "date", paramType = "query")
    })
    public ResponseEntity<CommonResultResponse> getMaintenanceBarChart(
            @RequestParam(value = "deviceId", required = false) Long deviceId,
            @RequestParam(value = "startDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startDate,
            @RequestParam(value = "endDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endDate
    ) throws Exception {
        EventCond cond = new EventCond();
        cond.setDeviceId(deviceId);
        cond.setStartTimeGreater(startDate);
        cond.setStartTimeLess(endDate);

        return ResponseHelper.success(eventService.maintenanceBarChart(cond));
    }

    @ApiOperation(value = "故障事件类型数量")
    @GetMapping(value = "/customers/types/count")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "customer_id", value = "客户id", dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "start_date", value = "开始时间", dataType = "date", paramType = "query"),
            @ApiImplicitParam(name = "end_date", value = "结束时间", dataType = "date", paramType = "query")
    })
    public ResponseEntity<CommonResultResponse> getCustomerTypeCount(
            @RequestParam(value = "customer_id", required = false) Long customerId,
            @RequestParam(value = "start_date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startDate,
            @RequestParam(value = "end_date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endDate
    ) throws Exception {
        EventCond cond = new EventCond();
        cond.setCustomerId(customerId);
        cond.setStartTimeGreater(startDate);
        cond.setStartTimeLess(endDate);

        return ResponseHelper.success(eventService.customerTypeCount(cond));
    }

}
